package com.example.controller;

import com.example.entity.Role;
import com.example.entity.User;
import com.example.entity.example.RoleExample;
import com.example.entity.example.UserExample;
import com.example.entity.vo.Register;
import com.example.service.RoleService;
import com.example.service.UserService;
import com.example.util.CustomConstant;
import com.example.util.CustomUtil;
import com.example.util.ResultEntity;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import redis.clients.jedis.Jedis;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.ResourceBundle;

@Controller
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Autowired
    private Jedis jedis;

    @Bean
    public Jedis setJedis() {
        ResourceBundle bundle = ResourceBundle.getBundle("properties/redis");
        String host = bundle.getString("host");
        int port = Integer.parseInt(bundle.getString("port"));
        String password = bundle.getString("password");
        jedis = new Jedis(host, port);
        // 权限认证
        jedis.auth(password);
        return jedis;
    }

    @PreAuthorize("hasRole('ROLE_2') or hasRole('ROLE_3') ")
    @ResponseBody
    @RequestMapping("/get/all/users.json")
    public ResultEntity<List<User>> getAllUsers(@RequestParam("page") Integer page,
                                                @RequestParam("limit") Integer limit,
                                                @RequestParam(value = "id", required = false) Integer id,
                                                @RequestParam(value = "roleId", required = false) Integer roleId,
                                                @RequestParam(value = "phone", required = false) String phone,
                                                @RequestParam(value = "username", required = false) String username
    ) {
        UserExample example = new UserExample();
        UserExample.Criteria criteria = example.createCriteria();
        if (id != null) {
            criteria.andIdEqualTo(id);
        }
        if (roleId != null) {
            criteria.andRoleIdEqualTo(roleId);
        }
        if (phone != null && !phone.isEmpty()) {
            criteria.andPhoneLike("%" + phone + "%");
        }
        if (username != null && !username.isEmpty()) {
            criteria.andUsernameLike("%" + username + "%");
        }
        List<User> allUsers = userService.getByExampleWithLimit(example, page, limit);
        int count = (int) userService.getCountByExample(example);
        return ResultEntity.createResultEntity(0, null, count, allUsers);
    }

    @RequestMapping("/get/verify/code")
    public void getVerifyCode(HttpServletResponse response, HttpSession session) throws IOException {
        int width = 120;
        int height = 40;
        Random ran = new Random();

        // 设置response头信息
        // 禁止缓存
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "no-cache");
        response.setDateHeader("Expires", 0);

        // 生成缓冲区image类
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        // 美化图片
        Graphics g = image.getGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, height);

        char[] ch = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
                't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
                'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8',
                '9'};

        StringBuilder code = new StringBuilder();

        for (int i = 0; i < 4; i++) {
            int index = ran.nextInt(62);
            code.append(ch[index]);
            g.setColor(CustomUtil.randomColor(ran));
            g.setFont(CustomUtil.randomFont(ran));
            g.drawString(ch[index] + "", width * i / 5 + 20, height / 2 + 10);
        }

        // 保存到session域
        session.setAttribute("verifyCode", code.toString());

        // 画干扰线
        for (int i = 0; i < 6; i++) {
            g.setColor(CustomUtil.randomColor(ran));
            int x1 = ran.nextInt(width);
            int x2 = ran.nextInt(width);
            int y1 = ran.nextInt(height);
            int y2 = ran.nextInt(height);
            g.drawLine(x1, y1, x2, y2);
        }

        // 画干扰点
        for (int i = 0; i < 10; i++) {
            g.setColor(CustomUtil.randomColor(ran));
            int x = ran.nextInt(width);
            int y = ran.nextInt(height);
            g.drawOval(x, y, 2, 2);
        }

        ImageIO.write(image, "JPEG", response.getOutputStream());
        response.getOutputStream().flush();
    }

    @PreAuthorize("hasRole('ROLE_3') ")
    @RequestMapping("/add/page.html")
    public String addPage(ModelMap modelMap) {
        List<Role> roleList = roleService.getByExampleWithLimit(new RoleExample(), 1, Integer.MAX_VALUE);
        modelMap.addAttribute("roleList", roleList);
        return "include/add-user";
    }

    @PreAuthorize("hasRole('ROLE_3') ")
    @ResponseBody
    @RequestMapping("/add")
    public ResultEntity<Object> addUser(@RequestBody User user) {
        if (userService.getUserByIdOrPhone(user.getPhone()) != null) {
            return ResultEntity.createResultEntity(-1, CustomConstant.MESSAGE_THE_PHONE_ALREADY_EXISTS, 0, null);
        }
        user.setCreatedate(new Date());
        String rowPassword = user.getPassword();
        String encodePassword = passwordEncoder.encode(rowPassword);
        user.setPassword(encodePassword);
        try {
            userService.addUser(user);
        } catch (Exception e) {
            return ResultEntity.createResultEntity(-1, e.getMessage(), 0, null);
        }
        return ResultEntity.createResultEntity(0, null, 0, null);
    }

    @PreAuthorize("hasRole('ROLE_3') ")
    @ResponseBody
    @RequestMapping("/remove")
    public ResultEntity<Object> removeById(@Param("id") Integer id) {
        try {
            userService.removeById(id);
        } catch (Exception e) {
            return ResultEntity.createResultEntity(-1, e.getMessage(), 0, null);
        }
        return ResultEntity.createResultEntity(0, null, 0, null);
    }

    @PreAuthorize("hasRole('ROLE_3') ")
    @ResponseBody
    @RequestMapping("/update")
    public ResultEntity<Object> updateById(@RequestBody User user) {
        try {
            String rowPassword = user.getPassword();
            String password = passwordEncoder.encode(rowPassword);
            user.setPassword(password);
            userService.updateById(user);
        } catch (Exception e) {
            return ResultEntity.createResultEntity(-1, e.getMessage(), 0, null);
        }
        return ResultEntity.createResultEntity(0, null, 0, null);
    }

    @ResponseBody
    @RequestMapping("/send/message/verify/code")
    public ResultEntity<String> sendMessageVerifyCode(@RequestParam("phone") String phone, HttpServletRequest request) {
        // 判断用户是否频繁发送
        String ip = CustomUtil.getIp(request);
        String key = CustomConstant.REDIS_VERIFY_CODE_PREFIX + ip;
        if (jedis.get(key) != null) {
            long cd = jedis.ttl(key);
            return ResultEntity.createResultEntity(-1, cd + "s后可再次发送", 0, null);
        }
        jedis.setex(key, 60, "");
        ResultEntity<String> resultEntity = CustomUtil.sendShortMessage(phone, 10);
        if (resultEntity.getCode() != 0) {
            return resultEntity;
        }
        String verifyCode = resultEntity.getData();
        jedis.setex(CustomConstant.REDIS_VERIFY_CODE_PREFIX + phone, 10 * 60, verifyCode);
        return ResultEntity.createResultEntity(0, null, 0, null);
    }

    @ResponseBody
    @RequestMapping("/do/register")
    public ResultEntity<Object> doRegister(@RequestBody Register register) {
        String phone = register.getPhone();
        String key = CustomConstant.REDIS_VERIFY_CODE_PREFIX + phone;
        String value = jedis.get(key);
        if (value == null || !value.equals(register.getVerifyCode())) {
            return ResultEntity.createResultEntity(-1, CustomConstant.MESSAGE_VERIFY_CODE_INVALID, 0, null);
        }
        jedis.del(key);

        if (userService.getUserByIdOrPhone(phone) != null) {
            return ResultEntity.createResultEntity(-1, CustomConstant.MESSAGE_THE_PHONE_ALREADY_EXISTS, 0, null);
        }

        // 密码加密
        String rowPassword = register.getPassword();
        String encodePassword = passwordEncoder.encode(rowPassword);
        register.setPassword(encodePassword);

        User user = new User();
        BeanUtils.copyProperties(register, user);
        user.setRoleId(1);
        user.setCreatedate(new Date());
        userService.addUser(user);
        return ResultEntity.createResultEntity(0, null, 0, null);
    }


    @ResponseBody
    @RequestMapping("/change/password")
    public ResultEntity<Object> changePassword(@RequestBody Register register) {
        String phone = register.getPhone();
        String key = CustomConstant.REDIS_VERIFY_CODE_PREFIX + phone;
        String value = jedis.get(key);
        if (value == null || !value.equals(register.getVerifyCode())) {
            return ResultEntity.createResultEntity(-1, CustomConstant.MESSAGE_VERIFY_CODE_INVALID, 0, null);
        }
        jedis.del(key);

        User user = userService.getUserByIdOrPhone(phone);
        if (user == null) {
            return ResultEntity.createResultEntity(-1, CustomConstant.MESSAGE_THE_PHONE_UNREGISTERED, 0, null);
        }

        // 密码加密
        String rowPassword = register.getPassword();
        String encodePassword = passwordEncoder.encode(rowPassword);

        // 修改密码
        user.setPassword(encodePassword);
        userService.updateById(user);
        return ResultEntity.createResultEntity(0, null, 0, null);
    }
}
